/**
 * Created by hanj on 2022/6/9 17:01
 */
package com.example.miniotest;


import io.minio.CreateMultipartUploadResponse;
import io.minio.ListPartsResponse;

import io.minio.messages.Part;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@RestController
@RequestMapping("file")
@Slf4j
public class FileUploader {

    @Autowired
    private MinIOConfig minIOConfig;

    /**
     * @param bucketName 桶名称
     * @param objectName 上传对象名称
     * @param filePath   上传对象路径
     */
    @PostMapping(value = "uploadFile")
    public void uploadFile(@RequestParam("bucketName") String bucketName,
                           @RequestParam("objectName") String objectName,
                           @RequestParam("filePath") String filePath) {
        // 使用MinIO服务的URL，端口，Access key和Secret key创建一个MinioClient对象
        PearlMinIOClient minIOClient = minIOConfig.getPearMinIOClient();
        //创建minio的工具类
        MinIOUtils minIOUtils = new MinIOUtils(minIOClient);
        // 检查存储桶是否已经存在
        minIOUtils.createBucket(bucketName);
        // 使用putObject上传一个文件到存储桶中。
        minIOUtils.uploadObject(bucketName, objectName, filePath);
        log.info("{} is successfully uploaded as {} to `{}` bucket.", filePath, objectName, bucketName);
    }


    /**
     * 获取文件的GET下载路径
     *
     * @param bucketName 桶名称
     * @param objectName 上传对象名称
     */
    @PostMapping(value = "getFileUrl")
    public String getFileUrl(@RequestParam("bucketName") String bucketName,
                             @RequestParam("objectName") String objectName) {
        // 使用MinIO服务的URL，端口，Access key和Secret key创建一个MinioClient对象
        PearlMinIOClient minIOClient = minIOConfig.getPearMinIOClient();
        //创建minio的工具类
        MinIOUtils minIOUtils = new MinIOUtils(minIOClient);
        // 使用putObject上传一个文件到存储桶中。
        String url = minIOUtils.presignedGetObject(bucketName, objectName);
        log.info("{},{} url is:{}", bucketName, objectName, url);
        return url;
    }

    /**
     * 删除文件
     *
     * @param bucketName 桶名称
     * @param objectName 桶内对象名称
     */
    @PostMapping(value = "removeFile")
    public void removeFile(@RequestParam("bucketName") String bucketName,
                           @RequestParam("objectName") String objectName) {
        // 使用MinIO服务的URL，端口，Access key和Secret key创建一个MinioClient对象
        PearlMinIOClient minIOClient = minIOConfig.getPearMinIOClient();
        //创建minio的工具类
        MinIOUtils minIOUtils = new MinIOUtils(minIOClient);
        // 删除文件。
        minIOUtils.removeObject(bucketName, objectName);
        log.info("文件：{}/{} ", bucketName, objectName);
    }

    /**
     * 返回分片上传需要的签名数据URL及 uploadId
     *
     * @param bucketName
     * @param fileName
     * @return
     */
    @GetMapping("/createMultipartUpload")
    @SneakyThrows
    @ResponseBody
    public Map<String, Object> createMultipartUpload(String bucketName, String fileName, Integer chunkSize) {
        // 使用MinIO服务的URL，端口，Access key和Secret key创建一个MinioClient对象
        PearlMinIOClient minIOClient = minIOConfig.getPearMinIOClient();
        //创建minio的工具类
        MinIOUtils minIOUtils = new MinIOUtils(minIOClient);
        // 1. 根据文件名创建签名
        Map<String, Object> result = new HashMap<>();
        // 2. 获取uploadId
        CreateMultipartUploadResponse response = minIOUtils.uploadId(bucketName, null, fileName, null, null);
        String uploadId = response.result().uploadId();
        result.put("uploadId", uploadId);
        // 3. 请求Minio 服务，获取每个分块带签名的上传URL
        Map<String, String> reqParams = new HashMap<>();
        reqParams.put("uploadId", uploadId);
        List<String> partList = new ArrayList<>();
        // 4. 循环分块数 从1开始
        for (int i = 1; i <= chunkSize; i++) {
            reqParams.put("partNumber", String.valueOf(i));
            String uploadUrl = minIOUtils.getPresignedObjectUrl(bucketName, fileName, reqParams);// 获取URL
            result.put("chunk_" + (i - 1), uploadUrl); // 添加到集合
        }
        return result;
    }

    /**
     * 分片上传完后合并
     *
     * @param objectName 文件全路径名称
     * @param uploadId   返回的uploadId
     * @return /
     */
    @GetMapping("/completeMultipartUpload")
    @SneakyThrows
    @ResponseBody
    public boolean completeMultipartUpload(String bucketName,String objectName, String uploadId) {
        // 使用MinIO服务的URL，端口，Access key和Secret key创建一个MinioClient对象
        PearlMinIOClient minIOClient = minIOConfig.getPearMinIOClient();
        //创建minio的工具类
        MinIOUtils minIOUtils = new MinIOUtils(minIOClient);
        try {
            Part[] parts = new Part[10000];
            ListPartsResponse partResult = minIOUtils.listMultipart(bucketName, null, objectName, 1000, 0, uploadId, null, null);
            int partNumber = 1;
            log.info(partResult.result().partList().size() + "========================");
            for (Part part : partResult.result().partList()) {
                parts[partNumber - 1] = new Part(partNumber, part.etag());
                partNumber++;
            }
            minIOUtils.completeMultipartUpload(bucketName, null, objectName, uploadId, parts, null, null);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }





}
